package com.racersystems.jracer;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

/**
 * RacerClient is a socket client that opens a socket to a racer server, sends messages to and receives
 * messages from it. As default the client prints no racer warning messages.
 * @author AK 23.11.2007
 */
public class RacerClient {

	private int socket;
	private String host = null;
	private Socket racerSocket = null;
	private PrintWriter out = null;
	private BufferedReader in = null;
    private boolean printWarningMessages=false;

	public RacerClient (String host, int socket) {
		this.host = host;
		this.socket = socket;
	}

	public void openConnection () throws RacerClientException{
		try {
			racerSocket = new Socket(host, socket);
			out = new PrintWriter(racerSocket.getOutputStream(), true);
			in = new BufferedReader(new InputStreamReader(racerSocket.getInputStream()));
		} catch (Exception ex) {
			throw new RacerClientException(ex.getMessage());
		}
	}

	public String send(String command) throws RacerClientException {
	    out.println(command);
		try {
			return parse(in.readLine());
		} catch (IOException ex) {
			throw new RacerClientException(ex.getMessage());
		}
	}

	private String parse(String result) throws RacerClientException{

	    if (result.charAt(1)=='a') { //answer message
	    	String answer="";
	    	String warning=null;
	    	int ini=result.indexOf('"',10);
	    	int fi=ini;
	    	boolean esFinal=false;
	    	while (!esFinal) {
	    		fi=result.indexOf('"',fi+1);
	    		esFinal=result.charAt(fi-1)!='\\';
	    	}
	    	answer=result.substring(ini+1,fi);
	    	if (fi+4<result.length()) warning=result.substring(fi+3,result.length()-1);
	    	if (printWarningMessages && warning!=null) System.out.println("WARNING RACER-SERVER:"+warning);
	    	return answer;

	    	} else if (result.charAt(1)=='o') { //warning message
	    	String warning=null;
	    	int start=result.indexOf('"',6);
	    	int end=result.length()-1;
	    	if (start<end-1) warning=result.substring(start+1,end);
	    	if (printWarningMessages && warning!=null) System.out.println("WARNING RACER-SERVER:"+warning);
	    		return null;

	        } else if (result.charAt(1)=='e') { //error message
	    	String error="";
	    	int iniMessage=result.indexOf(' ',7);
	    	int ini=result.indexOf('"',iniMessage);
	    	int fi=result.indexOf('"',ini+1);
	    	error=iniMessage+1<ini-1 ? result.substring(iniMessage+1,ini-1) : "";
	    	if (iniMessage+1<ini-1 && ini+1<fi) error=error+". ";
	    	error=error+result.substring(ini+1,fi);
	    		throw new RacerClientException(error);
	        }
	    throw new RacerClientException("Racer returned an unexpected answer:"+result);
	}

	public void closeConnection() throws RacerClientException{
	   try {
		   out.close();
		   in.close();
		   racerSocket.close();
	   } catch (IOException ex) {
		   throw new RacerClientException(ex.getMessage());
	   }
    }

	/**
	 * if set to true, the client prints all racer warning messages to system.out
	 * @param printWarningMessages
	 */
	public void setPrintWarningMessages(boolean printWarningMessages) {
		this.printWarningMessages = printWarningMessages;
	}
}